/*
* Copyright (c) 2022 Talkweb Co., Ltd.
*
* HDF is dual licensed: you can use it either under the terms of
* the GPL, or the BSD license, at your option.
* See the LICENSE file in the root of this repository for complete details.
*/

#include <stdio.h>
#include <stdlib.h>
#include "hdf_log.h"
#include "hdf_sbuf.h"
#include "hdf_io_service_if.h"

#define I2C_RD_CMD 456
#define I2C_WR_CMD 789

#define HDF_LOG_TAG "at24_test_log"
#define SAMPLE_SERVICE_NAME "at24_service"

static int write_data(struct HdfIoService *serv, uint16_t addr, uint8_t value)
{    
    int32_t ret;

    struct HdfSBuf *data = HdfSBufObtainDefaultSize();
    if (data == NULL) {
        HDF_LOGE("fail to obtain sbuf data");
        ret = HDF_DEV_ERR_NO_MEMORY;
        goto out;
    }   

    struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
    if (reply == NULL) {
        HDF_LOGE("fail to obtain sbuf reply");
        ret = HDF_DEV_ERR_NO_MEMORY;
        goto out;
    }   

    if (!HdfSbufWriteUint16(data, addr)) {
        printf("fail to write addr into FIFO\n");
        ret = HDF_FAILURE;
        goto out;
    }

    if (!HdfSbufWriteUint8(data, value)) {
        printf("fail to write value into FIFO\n");
        ret = HDF_FAILURE;
        goto out;
    }

    ret = serv->dispatcher->Dispatch(&serv->object, I2C_WR_CMD, data, reply);
    if (ret != HDF_SUCCESS) {
        printf("dispatch failed in %s\n", __func__);
        goto out;
    }

    const char *str = NULL;
    str = HdfSbufReadString(reply);
    if (str == NULL) {
        printf("fail to get drv reply\n");
        ret = HDF_FAILURE;
        goto out;
    }
    printf("Get reply is: %s\n", str);
    ret = HDF_SUCCESS;
    
out:    
    if(data != NULL)
        HdfSBufRecycle(data);
    return ret;
}

static int read_data(struct HdfIoService *serv, uint16_t addr, uint8_t * pval)
{       
    int32_t ret;

    struct HdfSBuf *data = HdfSBufObtainDefaultSize();
    if (data == NULL) {
        printf("fail to obtain sbuf data\n");
        ret = HDF_DEV_ERR_NO_MEMORY;
        goto out;
    }   
    struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
    if (reply == NULL) {
        printf("fail to obtain sbuf reply\n");
        ret = HDF_DEV_ERR_NO_MEMORY;
        goto out;
    }   

    if (!HdfSbufWriteUint16(data, addr)) {
        printf("fail to write addr into FIFO\n");
        ret = HDF_FAILURE;
        goto out;
    }

    ret = serv->dispatcher->Dispatch(&serv->object, I2C_RD_CMD, data, reply);
    if (ret != HDF_SUCCESS) {
        printf("dispatch in %s\n", __func__);
        goto out;
    }

    if (!HdfSbufReadUint8(reply, pval)) {
        printf("fail to get drv reply\n");
        ret = HDF_FAILURE;
        goto out;
    }

    const char *str = NULL;
    str = HdfSbufReadString(reply);
    if (str == NULL) {
        printf("fail to get drv reply\n");
        ret = HDF_FAILURE;
        goto out;
    }
    printf("Get reply is: data 0x%hhx, str: %s\n", *pval, str);
    ret = HDF_SUCCESS;    
out:    
    if(data != NULL)
        HdfSBufRecycle(data);
    if(reply != NULL)
        HdfSBufRecycle(reply);
    return ret;
}


int main()
{
    char cmd;
    uint16_t addr;
    uint8_t value;
    struct HdfIoService *serv = HdfIoServiceBind(SAMPLE_SERVICE_NAME);
    if (serv == NULL) {
        printf("fail to get service %s\n", SAMPLE_SERVICE_NAME);
        return HDF_FAILURE;
    }
   
   while(1){
        printf("input cmd(r/w/q): ");
        fflush(stdout);
        scanf("%c", &cmd);
        
        if(cmd == 'w'){
            printf("input addr and value: ");
            fflush(stdout);
            scanf("%hx%hhx", &addr, &value);
            write_data(serv, addr, value);
        }else if(cmd == 'r'){
            printf("input addr: ");
            fflush(stdout);
            scanf("%hx", &addr);
            read_data(serv, addr, &value);
        }else if(cmd == 'q'){
            break;
        }

   }

    HdfIoServiceRecycle(serv);
    return HDF_SUCCESS;
}